package com.brzjomo.secretiveworld.world.biome.feature;

import com.brzjomo.secretiveworld.init.ModBlocks;
import com.brzjomo.secretiveworld.init.ModFeatures;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Lists;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.HugeMushroomBlock;
import net.minecraft.block.SweetBerryBushBlock;
import net.minecraft.fluid.Fluids;
import net.minecraft.world.biome.Biome;
import net.minecraft.world.gen.GenerationStage;
import net.minecraft.world.gen.Heightmap;
import net.minecraft.world.gen.GenerationStage.Decoration;
import net.minecraft.world.gen.blockplacer.ColumnBlockPlacer;
import net.minecraft.world.gen.blockplacer.DoublePlantBlockPlacer;
import net.minecraft.world.gen.blockplacer.SimpleBlockPlacer;
import net.minecraft.world.gen.blockstateprovider.AxisRotatingBlockStateProvider;
import net.minecraft.world.gen.blockstateprovider.ForestFlowerBlockStateProvider;
import net.minecraft.world.gen.blockstateprovider.PlainFlowerBlockStateProvider;
import net.minecraft.world.gen.blockstateprovider.SimpleBlockStateProvider;
import net.minecraft.world.gen.blockstateprovider.WeightedBlockStateProvider;
import net.minecraft.world.gen.carver.WorldCarver;
import net.minecraft.world.gen.feature.BaseTreeFeatureConfig;
import net.minecraft.world.gen.feature.BigMushroomFeatureConfig;
import net.minecraft.world.gen.feature.BlockBlobConfig;
import net.minecraft.world.gen.feature.BlockClusterFeatureConfig;
import net.minecraft.world.gen.feature.BlockStateFeatureConfig;
import net.minecraft.world.gen.feature.BlockStateProvidingFeatureConfig;
import net.minecraft.world.gen.feature.BlockWithContextConfig;
import net.minecraft.world.gen.feature.Feature;
import net.minecraft.world.gen.feature.HugeTreeFeatureConfig;
import net.minecraft.world.gen.feature.IFeatureConfig;
import net.minecraft.world.gen.feature.LiquidsConfig;
import net.minecraft.world.gen.feature.MultipleRandomFeatureConfig;
import net.minecraft.world.gen.feature.MultipleWithChanceRandomFeatureConfig;
import net.minecraft.world.gen.feature.OreFeatureConfig;
import net.minecraft.world.gen.feature.ProbabilityConfig;
import net.minecraft.world.gen.feature.ReplaceBlockConfig;
import net.minecraft.world.gen.feature.SeaGrassConfig;
import net.minecraft.world.gen.feature.SphereReplaceConfig;
import net.minecraft.world.gen.feature.TreeFeatureConfig;
import net.minecraft.world.gen.feature.TwoFeatureChoiceConfig;
import net.minecraft.world.gen.feature.structure.BuriedTreasureConfig;
import net.minecraft.world.gen.feature.structure.MineshaftConfig;
import net.minecraft.world.gen.feature.structure.MineshaftStructure;
import net.minecraft.world.gen.feature.structure.OceanRuinConfig;
import net.minecraft.world.gen.feature.structure.OceanRuinStructure;
import net.minecraft.world.gen.feature.structure.ShipwreckConfig;
import net.minecraft.world.gen.feature.structure.VillageConfig;
import net.minecraft.world.gen.foliageplacer.AcaciaFoliagePlacer;
import net.minecraft.world.gen.foliageplacer.BlobFoliagePlacer;
import net.minecraft.world.gen.foliageplacer.PineFoliagePlacer;
import net.minecraft.world.gen.foliageplacer.SpruceFoliagePlacer;
import net.minecraft.world.gen.placement.AtSurfaceWithExtraConfig;
import net.minecraft.world.gen.placement.CaveEdgeConfig;
import net.minecraft.world.gen.placement.ChanceConfig;
import net.minecraft.world.gen.placement.CountRangeConfig;
import net.minecraft.world.gen.placement.DepthAverageConfig;
import net.minecraft.world.gen.placement.FrequencyConfig;
import net.minecraft.world.gen.placement.HeightWithChanceConfig;
import net.minecraft.world.gen.placement.IPlacementConfig;
import net.minecraft.world.gen.placement.NoiseDependant;
import net.minecraft.world.gen.placement.Placement;
import net.minecraft.world.gen.placement.TopSolidWithNoiseConfig;
import net.minecraft.world.gen.treedecorator.AlterGroundTreeDecorator;
import net.minecraft.world.gen.treedecorator.BeehiveTreeDecorator;
import net.minecraft.world.gen.treedecorator.CocoaTreeDecorator;
import net.minecraft.world.gen.treedecorator.LeaveVineTreeDecorator;
import net.minecraft.world.gen.treedecorator.TrunkVineTreeDecorator;

public class ModBiomeFeature {

	private static final BlockState GRASS = Blocks.GRASS.getDefaultState();
	private static final BlockState FERN = Blocks.FERN.getDefaultState();// 蕨类
	private static final BlockState PODZOL = Blocks.PODZOL.getDefaultState();// 灰化土
	private static final BlockState OAK_LOG = Blocks.OAK_LOG.getDefaultState();// 橡树原木
	private static final BlockState OAK_LEAVES = Blocks.OAK_LEAVES.getDefaultState();// 橡树树叶
	private static final BlockState JUNGLE_LOG = Blocks.JUNGLE_LOG.getDefaultState();// 从林木原木
	private static final BlockState JUNGLE_LEAVES = Blocks.JUNGLE_LEAVES.getDefaultState();// 从林木树叶
	private static final BlockState SPRUCE_LOG = Blocks.SPRUCE_LOG.getDefaultState();// 云杉原木
	private static final BlockState SPRUCE_LEAVES = Blocks.SPRUCE_LEAVES.getDefaultState();// 云杉树叶
	private static final BlockState ACACIA_LOG = Blocks.ACACIA_LOG.getDefaultState();// 金合欢树原木
	private static final BlockState ACACIA_LEAVES = Blocks.ACACIA_LEAVES.getDefaultState();// 金合欢树树叶
	private static final BlockState BIRCH_LOG = Blocks.BIRCH_LOG.getDefaultState();// 桦树原木
	private static final BlockState BIRCH_LEAVES = Blocks.BIRCH_LEAVES.getDefaultState();// 桦树树叶
	private static final BlockState DARK_OAK_LOG = Blocks.DARK_OAK_LOG.getDefaultState();// 深色橡树原木
	private static final BlockState DARK_OAK_LEAVES = Blocks.DARK_OAK_LEAVES.getDefaultState();// 深色橡树树叶
	private static final BlockState WATER = Blocks.WATER.getDefaultState();
	private static final BlockState LAVA = Blocks.LAVA.getDefaultState();
	private static final BlockState DIRT = Blocks.DIRT.getDefaultState();
	private static final BlockState GRAVEL = Blocks.GRAVEL.getDefaultState();// 沙砾
	private static final BlockState GRANITE = Blocks.GRANITE.getDefaultState();// 花岗岩
	private static final BlockState DIORITE = Blocks.DIORITE.getDefaultState();// 闪长岩
	private static final BlockState ANDESITE = Blocks.ANDESITE.getDefaultState();// 安山岩
	private static final BlockState COAL_ORE = Blocks.COAL_ORE.getDefaultState();
	private static final BlockState IRON_ORE = Blocks.IRON_ORE.getDefaultState();
	private static final BlockState GOLD_ORE = Blocks.GOLD_ORE.getDefaultState();
	private static final BlockState REDSTONE_ORE = Blocks.REDSTONE_ORE.getDefaultState();
	private static final BlockState DIAMOND_ORE = Blocks.DIAMOND_ORE.getDefaultState();
	private static final BlockState LAPIS_ORE = Blocks.LAPIS_ORE.getDefaultState();// 青金石矿
	private static final BlockState STONE = Blocks.STONE.getDefaultState();
	private static final BlockState EMERALD_ORE = Blocks.EMERALD_ORE.getDefaultState();// 绿宝石矿
	private static final BlockState INFESTED_STONE = Blocks.INFESTED_STONE.getDefaultState();
	private static final BlockState SAND = Blocks.SAND.getDefaultState();
	private static final BlockState CLAY = Blocks.CLAY.getDefaultState();
	private static final BlockState GRASS_BLOCK = Blocks.GRASS_BLOCK.getDefaultState();
	private static final BlockState MOSSY_COBBLESTONE = Blocks.MOSSY_COBBLESTONE.getDefaultState();// 原石
	private static final BlockState LARGE_FERN = Blocks.LARGE_FERN.getDefaultState();// 大型蕨类
	private static final BlockState TALL_GRASS = Blocks.TALL_GRASS.getDefaultState();
	private static final BlockState LILAC = Blocks.LILAC.getDefaultState();// 丁香
	private static final BlockState ROSE_BUSH = Blocks.ROSE_BUSH.getDefaultState();
	private static final BlockState PEONY = Blocks.PEONY.getDefaultState();// 牡丹
	private static final BlockState BROWN_MUSHROOM = Blocks.BROWN_MUSHROOM.getDefaultState();
	private static final BlockState RED_MUSHROOM = Blocks.RED_MUSHROOM.getDefaultState();
	private static final BlockState SEAGRASS = Blocks.SEAGRASS.getDefaultState();
	private static final BlockState PACKED_ICE = Blocks.PACKED_ICE.getDefaultState();
	private static final BlockState BLUE_ICE = Blocks.BLUE_ICE.getDefaultState();
	private static final BlockState LILY_OF_THE_VALLEY = Blocks.LILY_OF_THE_VALLEY.getDefaultState();// 铃兰
	private static final BlockState BLUE_ORCHID = Blocks.BLUE_ORCHID.getDefaultState();// 兰花
	private static final BlockState POPPY = Blocks.POPPY.getDefaultState();// 罂粟花
	private static final BlockState DANDELION = Blocks.DANDELION.getDefaultState();// 蒲公英
	private static final BlockState DEAD_BUSH = Blocks.DEAD_BUSH.getDefaultState();
	private static final BlockState MELON = Blocks.MELON.getDefaultState();// 西瓜
	private static final BlockState PUMPKIN = Blocks.PUMPKIN.getDefaultState();
	private static final BlockState SWEET_BERRY_BUSH = Blocks.SWEET_BERRY_BUSH.getDefaultState()
			.with(SweetBerryBushBlock.AGE, Integer.valueOf(3));// 浆果丛
	private static final BlockState FIRE = Blocks.FIRE.getDefaultState();
	private static final BlockState NETHERRACK = Blocks.NETHERRACK.getDefaultState();
	private static final BlockState LILY_PAD = Blocks.LILY_PAD.getDefaultState();// 睡莲
	private static final BlockState SNOW = Blocks.SNOW.getDefaultState();
	private static final BlockState JACK_O_LATERN = Blocks.JACK_O_LANTERN.getDefaultState();// 南瓜灯
	private static final BlockState SUNFLOWER = Blocks.SUNFLOWER.getDefaultState();
	private static final BlockState CACTUS = Blocks.CACTUS.getDefaultState();// 仙人掌
	private static final BlockState SUGAR_CANE = Blocks.SUGAR_CANE.getDefaultState();// 甘蔗
	private static final BlockState RED_MUSHROOM_BLOCK = Blocks.RED_MUSHROOM_BLOCK.getDefaultState()
			.with(HugeMushroomBlock.DOWN, Boolean.valueOf(false));
	private static final BlockState BROWN_MUSHROOM_BLOCK = Blocks.BROWN_MUSHROOM_BLOCK.getDefaultState()
			.with(HugeMushroomBlock.UP, Boolean.valueOf(true)).with(HugeMushroomBlock.DOWN, Boolean.valueOf(false));
	private static final BlockState MUSHROOM_STEM = Blocks.MUSHROOM_STEM.getDefaultState()
			.with(HugeMushroomBlock.UP, Boolean.valueOf(false)).with(HugeMushroomBlock.DOWN, Boolean.valueOf(false));
	private static final BlockState DIAMOND_BLOCK = Blocks.DIAMOND_BLOCK.getDefaultState();
	private static final BlockState LAUREL_LOG = ModBlocks.LAUREL_LOG.get().getDefaultState();
	private static final BlockState LAUREL_LEAVES = ModBlocks.LAUREL_LEAVES.get().getDefaultState();
	private static final BlockState LAUREL_SAPLING = ModBlocks.LAUREL_SAPLING.get().getDefaultState();

	// 树
	public static final TreeFeatureConfig OAK_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(4).heightRandA(2).foliageHeight(3).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig JUNGLE_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(JUNGLE_LOG), new SimpleBlockStateProvider(JUNGLE_LEAVES),
			new BlobFoliagePlacer(2, 0)))
					.baseHeight(4).heightRandA(8).foliageHeight(3)
					.decorators(ImmutableList.of(new CocoaTreeDecorator(0.2F), new TrunkVineTreeDecorator(),
							new LeaveVineTreeDecorator()))
					.ignoreVines().setSapling((net.minecraftforge.common.IPlantable) Blocks.JUNGLE_SAPLING).build();
	public static final TreeFeatureConfig JUNGLE_SAPLING_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(JUNGLE_LOG), new SimpleBlockStateProvider(JUNGLE_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(4).heightRandA(8).foliageHeight(3).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.JUNGLE_SAPLING).build();
	public static final TreeFeatureConfig PINE_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(SPRUCE_LOG), new SimpleBlockStateProvider(SPRUCE_LEAVES),
			new PineFoliagePlacer(1, 0))).baseHeight(7).heightRandA(4).trunkTopOffset(1).foliageHeight(3)
					.foliageHeightRandom(1).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.SPRUCE_SAPLING).build();
	public static final TreeFeatureConfig SPRUCE_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(SPRUCE_LOG), new SimpleBlockStateProvider(SPRUCE_LEAVES),
			new SpruceFoliagePlacer(2, 1))).baseHeight(6).heightRandA(3).trunkHeight(1).trunkHeightRandom(1)
					.trunkTopOffsetRandom(2).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.SPRUCE_SAPLING).build();
	public static final TreeFeatureConfig ACACIA_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(ACACIA_LOG), new SimpleBlockStateProvider(ACACIA_LEAVES),
			new AcaciaFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).heightRandB(2).trunkHeight(0).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.ACACIA_SAPLING).build();
	public static final TreeFeatureConfig BIRCH_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(BIRCH_LOG), new SimpleBlockStateProvider(BIRCH_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).foliageHeight(3).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.BIRCH_SAPLING).build();
	public static final TreeFeatureConfig field_230129_h_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(BIRCH_LOG), new SimpleBlockStateProvider(BIRCH_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.002F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.BIRCH_SAPLING).build();
	public static final TreeFeatureConfig field_230130_i_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(BIRCH_LOG), new SimpleBlockStateProvider(BIRCH_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).heightRandB(6).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.002F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.BIRCH_SAPLING).build();
	public static final TreeFeatureConfig SWAMP_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(3, 0))).baseHeight(5).heightRandA(3).foliageHeight(3).maxWaterDepth(1)
					.decorators(ImmutableList.of(new LeaveVineTreeDecorator()))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig FANCY_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(0, 0))).setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig OAK_TREE_WITH_MORE_BEEHIVES_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(4).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.05F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig field_230131_m_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(0, 0))).decorators(ImmutableList.of(new BeehiveTreeDecorator(0.002F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig FANCY_TREE_WITH_MORE_BEEHIVES_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(0, 0))).decorators(ImmutableList.of(new BeehiveTreeDecorator(0.05F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig field_230132_o_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(4).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.002F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig field_230133_p_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(4).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.02F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig field_230134_q_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(OAK_LOG), new SimpleBlockStateProvider(OAK_LEAVES),
			new BlobFoliagePlacer(0, 0))).decorators(ImmutableList.of(new BeehiveTreeDecorator(0.02F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING).build();
	public static final TreeFeatureConfig field_230135_r_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(BIRCH_LOG), new SimpleBlockStateProvider(BIRCH_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.02F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.BIRCH_SAPLING).build();
	public static final TreeFeatureConfig field_230136_s_ = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(BIRCH_LOG), new SimpleBlockStateProvider(BIRCH_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(5).heightRandA(2).foliageHeight(3).ignoreVines()
					.decorators(ImmutableList.of(new BeehiveTreeDecorator(0.05F)))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.BIRCH_SAPLING).build();
	public static final BaseTreeFeatureConfig JUNGLE_GROUND_BUSH_CONFIG = (new BaseTreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(JUNGLE_LOG), new SimpleBlockStateProvider(OAK_LEAVES))).baseHeight(4)
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.JUNGLE_SAPLING).build();
	public static final HugeTreeFeatureConfig DARK_OAK_TREE_CONFIG = (new HugeTreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(DARK_OAK_LOG), new SimpleBlockStateProvider(DARK_OAK_LEAVES))).baseHeight(6)
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.DARK_OAK_SAPLING).build();
	public static final HugeTreeFeatureConfig MEGA_SPRUCE_TREE_CONFIG = (new HugeTreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(SPRUCE_LOG), new SimpleBlockStateProvider(SPRUCE_LEAVES))).baseHeight(13)
					.heightInterval(15).crownHeight(13)
					.decorators(ImmutableList.of(new AlterGroundTreeDecorator(new SimpleBlockStateProvider(PODZOL))))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.SPRUCE_SAPLING).build();
	public static final HugeTreeFeatureConfig MEGA_PINE_TREE_CONFIG = (new HugeTreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(SPRUCE_LOG), new SimpleBlockStateProvider(SPRUCE_LEAVES))).baseHeight(13)
					.heightInterval(15).crownHeight(3)
					.decorators(ImmutableList.of(new AlterGroundTreeDecorator(new SimpleBlockStateProvider(PODZOL))))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.SPRUCE_SAPLING).build();
	public static final HugeTreeFeatureConfig MEGA_JUNGLE_TREE_CONFIG = (new HugeTreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(JUNGLE_LOG), new SimpleBlockStateProvider(JUNGLE_LEAVES))).baseHeight(10)
					.heightInterval(20)
					.decorators(ImmutableList.of(new TrunkVineTreeDecorator(), new LeaveVineTreeDecorator()))
					.setSapling((net.minecraftforge.common.IPlantable) Blocks.JUNGLE_SAPLING).build();

	// 简单树
	public static final TreeFeatureConfig LAUREL_TREE_CONFIG = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(LAUREL_LOG), new SimpleBlockStateProvider(LAUREL_LEAVES),
			new BlobFoliagePlacer(2, 0))).baseHeight(6).heightRandA(1).foliageHeight(3).trunkHeight(3).ignoreVines()
					.setSapling((net.minecraftforge.common.IPlantable) ModBlocks.LAUREL_SAPLING.get()).build();

	// 树叶带藤曼的树
	public static final TreeFeatureConfig TEST_TREE_CONFIG_2 = (new TreeFeatureConfig.Builder(
			new SimpleBlockStateProvider(DIAMOND_BLOCK), new SimpleBlockStateProvider(DIAMOND_ORE),
			new BlobFoliagePlacer(2, 0))).baseHeight(6).heightRandA(3).foliageHeight(4).maxWaterDepth(1)
					.decorators(ImmutableList.of(new LeaveVineTreeDecorator()))
					/* .setSapling((net.minecraftforge.common.IPlantable) Blocks.OAK_SAPLING) */.build();

	// 单一方块
	public static final BlockClusterFeatureConfig TEST_CONFIG_1 = (new BlockClusterFeatureConfig.Builder(
			new SimpleBlockStateProvider(GRASS), new SimpleBlockPlacer())).tries(32).build();

	// 多方快+黑名单
	public static final BlockClusterFeatureConfig DENSE_GRASS_WITH_FERN = (new BlockClusterFeatureConfig.Builder(
			(new WeightedBlockStateProvider()).addWeightedBlockstate(GRASS, 3).addWeightedBlockstate(FERN, 1),
			new SimpleBlockPlacer())).blacklist(ImmutableSet.of(PODZOL)).tries(64).build();

	// 白名单
	public static final BlockClusterFeatureConfig MELON_CONFIG = (new BlockClusterFeatureConfig.Builder(
			new SimpleBlockStateProvider(MELON), new SimpleBlockPlacer())).tries(32)
					.whitelist(ImmutableSet.of(GRASS_BLOCK.getBlock())).replaceable().func_227317_b_().build();

	public static final BlockClusterFeatureConfig LARGE_FERN_CONFIG = (new BlockClusterFeatureConfig.Builder(
			new SimpleBlockStateProvider(LARGE_FERN), new DoublePlantBlockPlacer())).tries(64).func_227317_b_().build();

	public static final BlockClusterFeatureConfig LILY_PAD_CONFIG = (new BlockClusterFeatureConfig.Builder(
			new SimpleBlockStateProvider(LILY_PAD), new SimpleBlockPlacer())).tries(10).build();

	// 添加功能
	public static void addCave(Biome biomeIn) {
		biomeIn.addCarver(GenerationStage.Carving.AIR,
				Biome.createCarver(WorldCarver.CAVE, new ProbabilityConfig(0.14285615F)));
	}

	public static void addLake(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.LOCAL_MODIFICATIONS,
				Feature.LAKE.withConfiguration(new BlockStateFeatureConfig(Blocks.WATER.getDefaultState()))
						.withPlacement(Placement.WATER_LAKE.configure(new ChanceConfig(4))));
	}

	public static void addTree(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.RANDOM_SELECTOR
						.withConfiguration(new MultipleRandomFeatureConfig(
								ImmutableList.of(
										Feature.FANCY_TREE.withConfiguration(FANCY_TREE_CONFIG).withChance(0.1F),
										Feature.NORMAL_TREE.withConfiguration(OAK_TREE_WITH_MORE_BEEHIVES_CONFIG)
												.withChance(0.6F),
										Feature.NORMAL_TREE.withConfiguration(TEST_TREE_CONFIG_2).withChance(0.1F)),
								Feature.NORMAL_TREE.withConfiguration(SPRUCE_TREE_CONFIG)))
						.withPlacement(
								Placement.COUNT_EXTRA_HEIGHTMAP.configure(new AtSurfaceWithExtraConfig(15, 0.1F, 1))));
	}

	public static void addSparseBamboo(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.BAMBOO.withConfiguration(new ProbabilityConfig(0.0F))
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(6))));
	}

	public static void addMelon(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.RANDOM_PATCH.withConfiguration(MELON_CONFIG)
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(1))));
	}

	public static void addDenseGrassWithFern(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.RANDOM_PATCH.withConfiguration(DENSE_GRASS_WITH_FERN)
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(8))));
	}

	public static void addLargeFern(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.RANDOM_PATCH.withConfiguration(LARGE_FERN_CONFIG)
						.withPlacement(Placement.COUNT_HEIGHTMAP_32.configure(new FrequencyConfig(3))));
	}

	public static void addUnderWaterGrass(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.SIMPLE_BLOCK
						.withConfiguration(new BlockWithContextConfig(SEAGRASS, new BlockState[] { DIRT },
								new BlockState[] { WATER }, new BlockState[] { WATER }))
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(6400))));
	}

	public static void addSparseUnderWaterGrass(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.SIMPLE_BLOCK
						.withConfiguration(new BlockWithContextConfig(SEAGRASS, new BlockState[] { DIRT },
								new BlockState[] { WATER }, new BlockState[] { WATER }))
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(640))));
	}

	public static void addLilyPad(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.RANDOM_PATCH.withConfiguration(LILY_PAD_CONFIG)
						.withPlacement(Placement.COUNT_HEIGHTMAP_DOUBLE.configure(new FrequencyConfig(5))));
	}

	public static void addLaurelTree(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.NORMAL_TREE.withConfiguration(LAUREL_TREE_CONFIG).withPlacement(
						Placement.COUNT_EXTRA_HEIGHTMAP.configure(new AtSurfaceWithExtraConfig(10, 0.1F, 1))));
	}
	
	public static void addSparseLaurelTree(Biome biomeIn) {
		biomeIn.addFeature(GenerationStage.Decoration.VEGETAL_DECORATION,
				Feature.NORMAL_TREE.withConfiguration(LAUREL_TREE_CONFIG).withPlacement(
						Placement.COUNT_EXTRA_HEIGHTMAP.configure(new AtSurfaceWithExtraConfig(1, 0.0F, 0))));
	}
}
